﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using LayerData;
using LayerData.Common;
using LayerEntity.Hotel;
using LayerEntity.Persona.Clientes;
using LayerEntity.Persona.Proveedores;
using LayerEntity.Persona.RecursosHumanos ;
using LayerEntity.Sistema;
using LayerEntity.Almacen;

namespace LayerLogic.Common
{
    public class CommonObjects
    {
        #region Variables
        public delegate void AddObject(string msj, EnumOperaciones op, EnumEstadoOperaciones est);

        public event AddObject UpdateList = delegate { };

        readonly IPostgreSqlConnectionInfo connectionInfo;
        readonly CommonObjectsList common;
        List<ETipoCliente> listTipoCliente;
        List<ETipoProveedor> listTipoProveedor;
        List<ESistemaPension> listSisPension;
        List<EAfp> listAfp;
        List<EAreas> listAreas;
        List<ECargos> listCargos;
        List<EGradoInstruccion> listGradosInstuccion;
        List<EProfesion> listProfesion;
        
        List<EDocumento> listDocumentos;
        List<EEstado> listEstados;
        
        List<EMoneda> listMondas;
        List<ETipoDocumento> listTipoDocumento;
        List<EUbigeo> listUbigeos;
        List<EHotel> listHotel;
        List<EEmpresa> listEmpresa;

        List<EEstadoCivil> listEcivil;
        List<EFormaPago> listFormaPago;
        List<ETarjetaCredito> listTarjetaCred;
        //List<EFactorCredito> listFactCred;
        List<EIgv> listIgv;
        List<ETipoCambio> listTc;
        List<ETranzaccion> listTranzac;
        List<ETipoInventario> listTipoInvent;
        List<ETipoOperacion> listOperacion;

        #endregion

        #region Constructores

        public CommonObjects()
        {
            this.InicializaVariables();
            this.connectionInfo = ObjectFactory.CreateConnectionInfo();
            this.common = new CommonObjectsList(this.connectionInfo);
        }

        public CommonObjects(IPostgreSqlConnectionInfo connection)
        {
            this.InicializaVariables();
            this.connectionInfo = connection;
            this.common = new CommonObjectsList(connection);
        }
        
        #endregion

        #region Metodos Privados
        private void InicializaVariables()
        {
            this.listTipoCliente = new List<ETipoCliente>();
            this.listTipoProveedor = new List<ETipoProveedor>();
            this.listAfp = new List<EAfp>();
            this.listAreas = new List<EAreas>();
            this.listCargos = new List<ECargos>();
            this.listGradosInstuccion = new List<EGradoInstruccion>();
            this.listProfesion = new List<EProfesion>();
            
            this.listDocumentos = new List<EDocumento>();
            this.listEstados = new List<EEstado>();
            
            this.listMondas = new List<EMoneda>();
            this.listTipoDocumento = new List<ETipoDocumento>();
            this.listUbigeos = new List<EUbigeo>();
            this.listHotel = new List<EHotel>();
            this.listEmpresa = new List<EEmpresa>();
            this.listEcivil = new List<EEstadoCivil>();
            listSisPension = new List<ESistemaPension>();
            listFormaPago = new List<EFormaPago>();
            listTarjetaCred = new List<ETarjetaCredito>();
            listIgv = new List<EIgv>();
            listTc = new List<ETipoCambio>();
            listTranzac = new List<ETranzaccion>();
            listTipoInvent = new List<ETipoInventario>();
            listOperacion = new List<ETipoOperacion>();
        }

        #endregion

        #region RecordManagerUbigeo
        public List<EUbigeo> GetUbigeoByDescripcion(string descripcion)
        {
            if (this.listUbigeos.Count == 0)
            {
                this.listUbigeos = this.common.GetUbigeo();
            }
            if (string.IsNullOrEmpty(descripcion.Trim()))
            {
                return this.listUbigeos;
            }
            else
            {
                this.strUbigeoSearch = descripcion;
                List<EUbigeo> query = this.listUbigeos.FindAll(FindUbigeoByDescription);
                if (query != null)
                {
                    return query;
                }
                else
                {
                    return new List<EUbigeo>();
                }
            }
        }

        string strUbigeoSearch = string.Empty;
        private Boolean FindUbigeoByDescription(EUbigeo ubigeo)
        {
            this.strUbigeoSearch = this.strUbigeoSearch.ToLower();
            Boolean returnValue = false;
            if (ubigeo.Departamento.ToLower().Contains(this.strUbigeoSearch) ||
                ubigeo.Provincia.ToLower().Contains(this.strUbigeoSearch) ||
                ubigeo.Distrito.ToLower().Contains(this.strUbigeoSearch))
            {
                returnValue = true;
            }
            return returnValue;
        }

        public EUbigeo GetUbigeoByUbigeo(string strUbigeo)
        {
            EUbigeo ubigeo = new EUbigeo();
            if (this.listUbigeos.Count == 0)
            {
                this.listUbigeos = this.common.GetUbigeo();
            }
            if (string.IsNullOrEmpty(strUbigeo.Trim()))
            {
                return ubigeo;
            }
            ubigeo = this.listUbigeos.Find(
                delegate(EUbigeo ubigeoFind)
                {
                    return ubigeoFind.Ubigeo == strUbigeo;
                });
            if (ubigeo == null)
            {
                ubigeo = new EUbigeo();
            }
            return ubigeo ;
        }

        #endregion

        #region Record Manager Tipos de Documentos

        internal void LoadTipoDocumento()
        {
            if (this.listTipoDocumento.Count == 0)
            {
                this.listTipoDocumento = this.common.GetTipoDocumentos();
            }
            foreach (ETipoDocumento doc in this.listTipoDocumento)
            {
                doc.IsSelectd = false;
            }
        }

        public List<ETipoDocumento> GetTipoDocumento()
        {
            this.LoadTipoDocumento();
            return this.listTipoDocumento;
        }

        public List<ETipoDocumento> GetTipoDocumento(string strTipo)
        {
            this.LoadDocumeno();

            if (string.IsNullOrEmpty(strTipo.Trim()))
            {
                return this.listTipoDocumento;
            }
            else
            {
                List<ETipoDocumento> query = this.listTipoDocumento.FindAll(delegate(ETipoDocumento td)
                {
                    return td.Descripcion.ToLower().Contains(strTipo.ToLower());
                });
                if (query != null)
                {
                    return query;
                }
                else
                {
                    return new List<ETipoDocumento>();
                }
            }
        }

        #endregion

        #region Record Manager Documentos

        internal void LoadDocumeno()
        {
            if (listDocumentos == null)
            {
                listDocumentos = new List<EDocumento>();
            }
            if (this.listDocumentos.Count == 0)
            {
                this.listDocumentos = this.common.GetDocumentos();
            }
        }

        public List<EDocumento> GetDocument()
        {
            this.LoadDocumeno();
            return this.listDocumentos;
        }

        /// <summary>
        /// Peremite buscar documentos de acuerdo a su tipo de documento asigando
        /// Los tipos de documentos pueden ser:
        /// Documentos de Identificacion
        /// Documentos de Compras 
        /// Documentos de Ventas
        /// Documentos de Almacen
        /// etc.
        /// </summary>
        /// <param name="tipoDocumento">
        /// El tipo de Documento a buscar.
        /// </param>
        /// <returns></returns>
        public List<EDocumento> GetDocument(int tipoDocumento)
        {
            this.LoadDocumeno();
            List<EDocumento> docs = new List<EDocumento>();
            if (tipoDocumento >= 0)
            {
                docs = this.listDocumentos.FindAll(delegate(EDocumento d)
                {
                    return d.CodigoSistema.Substring(tipoDocumento, 1) == "1";
                });
                if (docs == null)
                {
                    docs = new List<EDocumento>();
                }
            }
            return docs ;
        }

        public List<EDocumento> GetDocument(string strDocumento)
        {
            this.LoadDocumeno();
            if (string.IsNullOrEmpty(strDocumento.Trim()))
            {
                return this.listDocumentos;
            }
            else
            {
                List<EDocumento> query = this.listDocumentos.FindAll(
                    delegate(EDocumento doc)
                    {
                        return doc.Descripcion.ToLower().Contains(strDocumento.ToLower());
                    });

                if (query != null)
                {
                    return query;
                    //return new List<EDocumento>();
                }
                else
                {
                    return new List<EDocumento>();
                }
            }
        }

        public EDocumento GetDocument(long id)
        {
            LoadDocumeno();
            return this.listDocumentos.Find(delegate(EDocumento dc)
            {
                return dc.IdDocumento == id;
            });
        }

        public void AddDocumento(EDocumento doc)
        {
            if (doc != null)
            {
                this.UpdateList("Se Agrego un Nuevo Documento", EnumOperaciones.AddCollection, EnumEstadoOperaciones.Complete);
                int index = this.listDocumentos.FindIndex(delegate(EDocumento docSerach)
                {
                    return doc.IdDocumento == docSerach.IdDocumento;
                });

                if (index > -1)
                {
                    this.listDocumentos[index] = doc;
                }
                else
                {
                    this.listDocumentos.Add(doc);
                }
            }
            else
            {
                this.UpdateList("Parametro es Null", EnumOperaciones.AddCollection, EnumEstadoOperaciones.Error);
            }
        }

        #endregion

        #region RecordManager Tipos de Estados
        public List<EHotel> GetHoteles()
        {
            if (this.listHotel.Count == 0)
            {
                this.listHotel = this.common.GetHoteles();
            }
            return this.listHotel;
        }

        public List<EEstado> GetEstados()
        {
            if (this.listEstados.Count == 0)
            {
                this.listEstados = this.common.GetEstados();
            }
            return this.listEstados;
        }

        public List<EMoneda> GetMoneda()
        {
            if (this.listMondas.Count == 0)
            {
                this.listMondas = this.common.GetMonedas();
            }
            return this.listMondas;
        }

        public EMoneda GetMoneda(int id) {
            if (listMondas.Count == 0) {
                listMondas = common.GetMonedas();
            }
            return listMondas.Find(delegate(EMoneda e) {
                return e.IdMoneda == id;
            });
        }

        public EEstado GetEstadoById(int id)
        {
            if (this.listEstados.Count == 0)
            {
                this.GetEstados();
            }
            return this.listEstados.Find(delegate(EEstado est)
            {
                return est.IdEstado == id;
            });
        }

        public DataTable GetListaSucursal(EHotel obj)
        {
            return this.common.GetListaSucursal(obj);
        }

        #endregion

        #region Record Manager Persona
        /// <summary>
        /// Retorna una lista con los tipos de clientes registrados
        /// </summary>
        /// <returns></returns>
        public List<ETipoCliente> GetTipoClientes()
        {
            if (this.listTipoCliente == null)
            {
                this.listTipoCliente = new List<ETipoCliente>();
            }
            if (this.listTipoCliente.Count == 0)
            {
                this.listTipoCliente = this.common.GetTipoClientes();
            }
            return this.listTipoCliente;
        }

        public ETipoCliente GetClientType(int id)
        {
            return this.listTipoCliente.Find(delegate(ETipoCliente t)
            {
                return t.IdTipoCliente == id;
            });
        }

        public List<ETipoProveedor> GetTipoProveedores()
        {
            if (this.listTipoProveedor == null)
            {
                this.listTipoProveedor = new List<ETipoProveedor>();
            }
            if (this.listTipoProveedor.Count == 0)
            {
                this.listTipoProveedor = this.common.GetTipoProveedor();
            }
            return this.listTipoProveedor;
        }

        public ETipoProveedor GetSupplierType(int id)
        { 
            return this.listTipoProveedor.Find(delegate(ETipoProveedor tp)
            {
                return tp.IdTipoProveedor == id;
            });
        }

        internal void LoadGradoIntruccion()
        {
            if (this.listGradosInstuccion.Count == null)
            {
                this.listGradosInstuccion = new List<EGradoInstruccion>();
            }
            if (this.listGradosInstuccion.Count == 0)
            {
                this.listGradosInstuccion = this.common.GetGradoInstruccion();
            }
        }

        public List<EGradoInstruccion> GetGradoInstruccion()
        {
            LoadGradoIntruccion();
            return this.listGradosInstuccion;
        }

        public EGradoInstruccion GetGradoInstruccion(int id)
        {
            LoadGradoIntruccion();
            return listGradosInstuccion.Find(delegate(EGradoInstruccion g)
            {
                return g.IdGradoInstruccion == id;
            });
        }

        internal void LoadEstadoCivil()
        {
            if (this.listEcivil == null)
            {
                this.listEcivil = new List<EEstadoCivil>();
            }
            if (this.listEcivil.Count == 0)
            {
                this.listEcivil = this.common.GetEstadosCiviles();
            }
        }

        public List<EEstadoCivil> GetEstadoCivil()
        {
            LoadEstadoCivil();
            return this.listEcivil;
        }

        public EEstadoCivil GetEstadoCivil(int id)
        {
            LoadEstadoCivil();
            return listEcivil.Find(delegate(EEstadoCivil ec)
            {
                return ec.IdEstadoCivil == id;
            });
        }

        private void LoadAfp()
        {
            if (listAfp == null)
            {
                listAfp = new List<EAfp>();
            }
            if (listAfp.Count == 0)
            {
                listAfp = common.GetAfps();
            }
        }

        public List<EAfp> GetAfp(int sistema)
        {
            LoadAfp();
            return listAfp.FindAll(delegate(EAfp afp)
            {
                return afp.Tipo == sistema;
            });
        }

        public EAfp GetAfp(Int64 idAfp)
        {
            LoadAfp();

            return listAfp.Find(delegate(EAfp afp)
            {
                return afp.IdAfp == idAfp;
            });
        }

        public List<ESistemaPension> GetSistemaPension()
        {
            if (listSisPension == null)
            {
                listSisPension = new List<ESistemaPension>();
            }
            if (listSisPension.Count == 0)
            {
                listSisPension.Add(new ESistemaPension() { Descripcion = "SPP", IdSistemaPension = 1 });
                listSisPension.Add(new ESistemaPension() { Descripcion = "SNP", IdSistemaPension = 2 });
            }
            return listSisPension;
        }

        public List<EProfesion> GetProfesion()
        {
            if (listProfesion == null)
            {
                listProfesion = new List<EProfesion>();
            }
            if (listProfesion.Count == 0)
            {
                listProfesion = common.GetProfesiones();
            }
            return listProfesion;
        }

        public EProfesion GetProfesion(int id)
        {
            if (listProfesion == null)
            {
                listProfesion = new List<EProfesion>();
            }
            if (listProfesion.Count == 0)
            {
                listProfesion = common.GetProfesiones();
            }
            return listProfesion.Find(delegate(EProfesion p)
            {
                return p.IdProfesion == id;
            });
        }

        internal void LoadCargos()
        {
            if (listCargos == null)
            {
                listCargos = new List<ECargos>();
            }
            if (listCargos.Count == 0)
            {
                listCargos = common.GetCargos();
            }
        }

        public List<ECargos> GetCargos()
        {
            LoadCargos();
            return listCargos;
        }

        public ECargos GetCargos(int id)
        {
            LoadCargos();
            return listCargos.Find(delegate(ECargos c)
            {
                return c.IdCargo == id;
            });
        }

        internal void LoadAreas()
        {
            if (listAreas == null)
            {
                listAreas = new List<EAreas>();
            }
            if (listAreas.Count == 0)
            {
                listAreas = common.GetAreas();
            }
        }

        public List<EAreas> GetAreas()
        {
            LoadAreas();
            return listAreas;
        }

        public EAreas GetAreas(int id)
        {
            LoadAreas();
            return listAreas.Find(delegate(EAreas a)
            {
                return a.IdArea == id;
            });
        }

        #endregion

        public List<EEmpresa> GetEmpresas()
        {
            if (this.listEmpresa.Count == 0)
            {
                this.listEmpresa = this.common.GetEmpresas();
            }
            return this.listEmpresa;
        }

        /// <summary>
        /// Retorna una lista con las formas de pago registrados
        /// </summary>
        /// <returns></returns>
        internal void LoadFormaPago()
        {
            if (this.listFormaPago == null)
            {
                this.listFormaPago = new List<EFormaPago>();
            }
            if (this.listFormaPago.Count == 0)
            {
                this.listFormaPago = this.common.GetFormaPago();
            }
        }

        public virtual List<EFormaPago> GetFormaPago(string opCompra, bool onlyCompras)
        {
            this.LoadFormaPago();
            if (string.IsNullOrEmpty(opCompra.Trim()))
            {
                return this.listFormaPago;
            }
            else
            {
                List<EFormaPago> query = this.listFormaPago.FindAll(
                    delegate(EFormaPago doc)
                    {
                        return doc.OpcionCompra.ToLower().Equals(opCompra.ToLower());
                    });

                if (query != null)
                {
                    return query;
                    //return new List<EDocumento>();
                }
                else
                {
                    return new List<EFormaPago>();
                }
            }
        }

        public List<EFormaPago> GetFormaPago(string opCaja)
        {
            this.LoadFormaPago();
            if (string.IsNullOrEmpty(opCaja.Trim()))
            {
                return this.listFormaPago;
            }
            else
            {
                List<EFormaPago> query = this.listFormaPago.FindAll(
                    delegate(EFormaPago doc)
                    {
                        return doc.Op_caja.ToLower().Contains(opCaja.ToLower());
                    });

                if (query != null)
                {
                    return query;
                    //return new List<EDocumento>();
                }
                else
                {
                    return new List<EFormaPago>();
                }
            }
        }

        public List<ETarjetaCredito> GetTarjetaCredito()
        {
            if (this.listTarjetaCred.Count == 0)
            {
                this.listTarjetaCred = this.common.GetTarjetaCredito();
            }
            return this.listTarjetaCred;
        }



        public DataTable GetFactCredito(ESistema obj)
        {
            return common.GetFactCredito(obj);
        }
        public DataTable GetListadoPersonal(ESistema obj)
        {
            return common.GetListadoPersonal(obj);
        }

        public List<ETipoOperacion> GetOperaciones() {
            if (listOperacion.Count == 0) {
                listOperacion = common.GetOperaciones();
            }
            return listOperacion;
        }
        public DataTable GetListadoTipoOperacion(ESistema obj)
        {
            return common.GetListadoTipoOperacion(obj);
        }
        public List<EIgv> GetIgv(int id)
        {
            if (this.listIgv.Count == 0)
            {
                this.listIgv = this.common.GetIgv();
            }
            if (id==0)
            {
                return this.listIgv;
            }
            else
            {
                List<EIgv> query = this.listIgv.FindAll(
                    delegate(EIgv doc)
                    {
                        return doc.Id_Igv==id;
                    });

                if (query != null)
                {
                    return query;
                }
                else
                {
                    return new List<EIgv>();
                }
            }

           // return this.listIgv;
        }

        public List<ETipoCambio> GetTipoCambio(int id)
        {
            if (this.listTc.Count == 0)
            {
                this.listTc = this.common.GetTipoCambio();
            }
            if (id == 0)
            {
                return this.listTc;
            }
            else
            {
                List<ETipoCambio> query = this.listTc.FindAll(
                    delegate(ETipoCambio doc)
                    {
                        return doc.Id_Tipocambio == id;
                    });

                if (query != null)
                {
                    return query;
                }
                else
                {
                    return new List<ETipoCambio>();
                }
            }

            //return this.listTc;
        }
        public List<ETranzaccion> GetTranzaccion()
        {
            if (this.listTranzac.Count == 0)
            {
                this.listTranzac = this.common.GetTranzaccion();
            }
            return this.listTranzac;
        }
       public List<ETipoInventario> GetTipoInventario()
       
        {
            if (this.listTipoInvent.Count == 0)
            {
                this.listTipoInvent = this.common.GetTipoInventario();
            }
            return this.listTipoInvent;
        }
        public DataTable GetListaSeriesDocumento(ESistema obj)
        {
            return common.GetListaSeriesDocumento(obj);
        }
    }
}